package cn.wuwenyao.patch.generator;

import java.io.File;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNLogEntryPath;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.BasicAuthenticationManager;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.ISvnObjectReceiver;
import org.tmatesoft.svn.core.wc2.SvnLog;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
import org.tmatesoft.svn.core.wc2.SvnRevisionRange;
import org.tmatesoft.svn.core.wc2.SvnTarget;

import cn.wuwenyao.patch.generator.entity.PatchInfo;
import cn.wuwenyao.patch.generator.entity.ProjectInfo;
import cn.wuwenyao.patch.generator.entity.SvnProjectInfo;
import cn.wuwenyao.patch.generator.enums.VersionManagerType;
import cn.wuwenyao.patch.generator.utils.ZipUtil;

/***
 * svn 补丁生成器
 * 
 * @author wwy
 *
 */
public class SvnPatchGenerator implements PatchGenerator {
	
	private static final Logger LOG = LoggerFactory.getLogger(SvnPatchGenerator.class);
	
	@Override
	public boolean support(VersionManagerType manageType) {
		return manageType.equals(VersionManagerType.SVN);
	}
	
	@Override
	public void generatePatch(ProjectInfo projectInfo, PatchInfo patchInfo) throws SVNException {
		if (projectInfo instanceof SvnProjectInfo) {
			
		} else {
			throw new RuntimeException("ProjectInfo只支持SvnProjectInfo实例");
		}
		SvnProjectInfo svnProjectInfo = (SvnProjectInfo) projectInfo;
		SvnOperationFactory svnOperationFactory = new SvnOperationFactory();
		patchInfo.setPatchFileDir(
				patchInfo.getPatchFileDir() + "/" + DateFormatUtils.format(new Date(), "yyyy-MM-dd-hh-mm-ss"));
		// svn的 url
		final SVNURL url = SVNURL.parseURIEncoded(svnProjectInfo.getSvnUrl());
		// 设置svn用户名和密码
		svnOperationFactory.setAuthenticationManager(BasicAuthenticationManager
				.newInstance(svnProjectInfo.getSvnUsername(), svnProjectInfo.getSvnPassword().toCharArray()));
		// 获取日志信息
		final SvnLog log = svnOperationFactory.createLog();
		log.addRange(SvnRevisionRange.create(SVNRevision.create(Long.parseLong(patchInfo.getStartVersion())),
				SVNRevision.create(Long.parseLong(patchInfo.getEndVersion()))));
		log.setDiscoverChangedPaths(true);
		log.setSingleTarget(SvnTarget.fromURL(url));
		// 文件变更列表
		Set<String> changeFiles = new HashSet<>();
		log.setReceiver(new ISvnObjectReceiver<SVNLogEntry>() {
			@Override
			public void receive(SvnTarget svnTarget, SVNLogEntry svnLogEntry) throws SVNException {
				// 每个版本执行一次
				LOG.info("版本:{},作者:{},时间:{}", svnLogEntry.getRevision(), svnLogEntry.getAuthor(),
						LocalDateTime.ofInstant(svnLogEntry.getDate().toInstant(), ZoneId.systemDefault()));
				LOG.info("修改内容:{}", svnLogEntry.getMessage());
				Map<String, SVNLogEntryPath> map = svnLogEntry.getChangedPaths();
				if (map.size() > 0) {
					Set<String> set = map.keySet();
					for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
						String fileName = iterator.next();
						SVNLogEntryPath path = map.get(fileName);
						LOG.info("{}:{}", path.getType(), fileName);
						if (path.getType() != 'D') {
							changeFiles.add(fileName);
						}
					}
				}
			}
		});
		log.run();
		// 复制文件到补丁目录
		for (String changeFile : changeFiles) {
			copyFileToPatchDir(changeFile, projectInfo, patchInfo);
		}
		File zipFile = ZipUtil.zip(patchInfo.getPatchFileDir());
		LOG.info("生成补丁包:{}", zipFile.getPath());
	}
	
}
